home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / tcshsrc.zoo / tcsh / sh.proc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-13  |  47.3 KB  |  1,935 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.proc.c,v 3.9 1991/08/05 23:02:13 christos Exp $ */
  2. /*
  3.  * sh.proc.c: Job manipulations
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "config.h"
  38. RCSID("$Id: sh.proc.c,v 3.9 1991/08/05 23:02:13 christos Exp $")
  39.  
  40. #include "sh.h"
  41. #include "ed.h"
  42. #include "tc.h"
  43.  
  44. /*
  45.  * a little complicated #include <sys/wait.h>! :-(
  46.  */
  47. #if SVID > 0
  48. # ifdef hpux
  49. #  ifndef __hpux
  50. #   include "tc.wait.h"    /* 6.5 broke <sys/wait.h> */
  51. #  else
  52. #   ifndef POSIX
  53. #    define _BSD
  54. #   endif
  55. #   ifndef _CLASSIC_POSIX_TYPES
  56. #    define _CLASSIC_POSIX_TYPES
  57. #   endif
  58. #   include <sys/wait.h> /* 7.0 fixed it again */
  59. #  endif /* __hpux */
  60. # else /* hpux */
  61. #  if defined(OREO) || defined(IRIS4D) || defined(POSIX)
  62. #   include <sys/wait.h>
  63. #  else    /* OREO || IRIS4D || POSIX */
  64. #   include "tc.wait.h"
  65. #  endif /* OREO || IRIS4D || POSIX */
  66. # endif    /* hpux */
  67. #else /* SVID == 0 */
  68. # include <sys/wait.h>
  69. #endif /* SVID == 0 */
  70.  
  71. #if !defined(NSIG) && defined(SIGMAX)
  72. # define NSIG (SIGMAX+1)
  73. #endif /* !NSIG && SIGMAX */
  74.  
  75. #ifdef aiws
  76. # undef HZ
  77. # define HZ 16
  78. #endif /* aiws */
  79.  
  80. #ifndef HZ
  81. # define HZ    100        /* for division into seconds */
  82. #endif
  83.  
  84. #if (defined(_BSD) && defined(_BSD_INCLUDES))
  85. # define BSDWAIT
  86. #endif
  87. #ifndef WTERMSIG
  88. # define WTERMSIG(w)    (((union wait *) &(w))->w_termsig)
  89. # ifndef BSDWAIT
  90. #  define BSDWAIT
  91. # endif
  92. #endif /* !WTERMSIG */
  93. #ifndef WEXITSTATUS
  94. # define WEXITSTATUS(w)    (((union wait *) &(w))->w_retcode)
  95. #endif /* !WEXITSTATUS */
  96. #ifndef WSTOPSIG
  97. # define WSTOPSIG(w)    (((union wait *) &(w))->w_stopsig)
  98. #endif /* WSTOPSIG */
  99.  
  100. #ifndef WCOREDUMP
  101. # ifdef BSDWAIT
  102. #  define WCOREDUMP(w)    (((union wait *) &(w))->w_coredump)
  103. # else /* !BSDWAIT */
  104. #  define WCOREDUMP(w)    ((w) & 0200)
  105. # endif /* !BSDWAIT */
  106. #endif /* !WCOREDUMP */
  107.  
  108. /*
  109.  * C Shell - functions that manage processes, handling hanging, termination
  110.  */
  111.  
  112. #define BIGINDEX    9    /* largest desirable job index */
  113.  
  114. #ifdef BSDTIMES
  115. # if defined(sun) || defined(hp9000)
  116. static struct rusage zru = {{0L, 0L}, {0L, 0L}, 0L, 0L, 0L, 0L,
  117.                 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L};
  118.  
  119. # else /* !sun && !hp9000 */
  120. #  if defined(masscomp) || defined(__MINT__)
  121. /*
  122.  * Initialization of this structure under RTU 4.1A & RTU 5.0 is problematic
  123.  * because the first two elements are unions of a time_t and a struct timeval.
  124.  * So we'll just have to trust the loader to do the "right thing", DAS DEC-90.
  125.  */
  126.  
  127. /* MiNT is missing a lot of fields, so we also trust the loader (we can
  128.  * trust it) to avoid getting errors from the compiler
  129.  */
  130. static struct rusage zru;
  131. #  else    /* masscomp */
  132. static struct rusage zru = {{0L, 0L}, {0L, 0L}, 0, 0, 0, 0, 0, 0, 0, 
  133.                 0, 0, 0, 0, 0, 0};
  134. #  endif /* masscomp */
  135. # endif    /* !sun && !hp9000 */
  136. #else /* ! BSDTIMES */
  137. # ifdef _SEQUENT_
  138. static struct process_stats zru = {{0L, 0L}, {0L, 0L}, 0, 0, 0, 0, 0, 0, 0,
  139.                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  140. # else /* !_SEQUENT_ */
  141. static struct tms zru = {0L, 0L, 0L, 0L}, lru = {0L, 0L, 0L, 0L};
  142. # endif    /* !_SEQUENT_ */
  143. #endif /* !BSDTIMES */
  144.  
  145. #ifndef RUSAGE_CHILDREN
  146. # define    RUSAGE_CHILDREN    -1
  147. #endif
  148.  
  149. static    void         pflushall    __P((void));
  150. static    void         pflush        __P((struct process *));
  151. static    void         pclrcurr    __P((struct process *));
  152. static    void         padd        __P((struct command *));
  153. static    int         pprint        __P((struct process *, int));
  154. static    void         ptprint    __P((struct process *));
  155. static    void         pads        __P((Char *));
  156. static    void         pkill        __P((Char **, int));
  157. static    struct process    *pgetcurr    __P((struct process *));
  158. static    void         okpcntl    __P((void));
  159.  
  160. #ifdef __MINT__
  161. /*
  162.  * MiNT's fork() is a lot like vfork() in some respects; in particular,
  163.  * if we set job control signals to SIG_DFL after fork() and then
  164.  * get a signal, our parent will never be able to reclaim the address
  165.  * space and everything will hang :-(. Solution: rather than SIG_DFL,
  166.  * set the signals to a null signal handler; if we exec(), they will
  167.  * be set to SIG_DFL automatically, and before then the signals will
  168.  * effectively be ignored.
  169.  */
  170.  
  171. void
  172. sig_tmp_ign(int sig)
  173. {
  174. /* do nothing, and rely on the magic of restartable system calls :-) */
  175. }
  176. #endif
  177.  
  178. /*
  179.  * pchild - called at interrupt level by the SIGCHLD signal
  180.  *    indicating that at least one child has terminated or stopped
  181.  *    thus at least one wait system call will definitely return a
  182.  *    childs status.  Top level routines (like pwait) must be sure
  183.  *    to mask interrupts when playing with the proclist data structures!
  184.  */
  185. sigret_t
  186. /*ARGSUSED*/
  187. pchild(snum)
  188. int snum;
  189. {
  190.     register struct process *pp;
  191.     register struct process *fp;
  192.     register int pid;
  193.     extern int insource;
  194. #ifdef BSDWAIT
  195.     union wait w;
  196. #else /* !BSDWAIT */
  197.     int     w;
  198. #endif /* !BSDWAIT */
  199.     int     jobflags;
  200. #ifdef BSDTIMES
  201.     struct rusage ru;
  202. #else /* !BSDTIMES */
  203. # ifdef _SEQUENT_
  204.     struct process_stats ru;
  205.     struct process_stats cpst1, cpst2;
  206.     timeval_t tv;
  207. # else /* !_SEQUENT_ */
  208.     struct tms proctimes;
  209.  
  210.     if (!timesdone) {
  211.     timesdone++;
  212.     (void) times(&shtimes);
  213.     }
  214. # endif    /* _SEQUENT_ */
  215. #endif /* BSDTIMES */
  216.  
  217. #ifdef JOBDEBUG
  218.     xprintf("pchild()\n");
  219. #endif    /* JOBDEBUG */
  220.  
  221. /* Christos on where the signal(SIGCHLD, pchild) shoud be:
  222.  *
  223.  * I think that it should go *after* the wait, unlike most signal handlers.
  224.  *
  225.  * In release two (for which I have manuals), it says that wait will remove
  226.  * the first child from the queue of dead children.
  227.  * All the rest of the children that die while in the signal handler of the
  228.  * SIGC(H)LD, will be placed in the queue. If signal is called to re-establish
  229.  * the signal handler, and there are items in the queue, the process will
  230.  * receive another SIGC(H)LD before signal returns. BTW this is from the
  231.  * manual page on comp-sim... Maybe it is not applicable to the hp's, but
  232.  * I read on the news in comp.unix.wizards or comp.unix.questions yesterday
  233.  * that another person was claiming the the signal() call should be after
  234.  * the wait().
  235.  */
  236.  
  237. loop:
  238.     errno = 0;            /* reset, just in case */
  239. #ifdef JOBDEBUG
  240.     xprintf("Waiting...\n");
  241.     flush();
  242. #endif
  243. #ifdef BSDJOBS
  244. # ifdef BSDTIMES
  245.     /* both a wait3 and rusage */
  246. #  ifndef BSDWAIT
  247.     pid = wait3(&w,
  248.        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
  249. #  else /* BSDWAIT */
  250.     pid = wait3(&w.w_status,
  251.        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
  252. #  endif /* BSDWAIT */
  253. # else /* !BSDTIMES */
  254. #  ifdef _SEQUENT_
  255.     (void) get_process_stats(&tv, PS_SELF, 0, &cpst1);
  256.     pid = waitpid(-1, &w,
  257.         (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
  258.     (void) get_process_stats(&tv, PS_SELF, 0, &cpst2);
  259.     pr_stat_sub(&cpst2, &cpst1, &ru);
  260. #  else    /* !_SEQUENT_ */
  261. #   ifndef POSIX
  262.     /* we have a wait3, but no rusage stuff */
  263.     pid = wait3(&w.w_status,
  264.      (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0);
  265. #   else /* POSIX */
  266.     pid = waitpid(-1, &w,
  267.         (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
  268. #   endif /* POSIX */
  269. #  endif /* !_SEQUENT_ */
  270. # endif    /* !BSDTIMES */
  271. #else /* !BSDJOBS */
  272. # ifdef BSDTIMES
  273.     /* both a wait3 and rusage */
  274. #  ifdef hpux
  275.     pid = wait3(&w.w_status, WNOHANG, 0);
  276. #  else    /* !hpux */
  277.     pid = wait3(&w.w_status, WNOHANG, &ru);
  278. #  endif /* !hpux */
  279. # else /* !BSDTIMES */
  280. #  if SVID < 3
  281.     /* no wait3, therefore no rusage */
  282.     /* on Sys V, this may hang.  I hope it's not going to be a problem */
  283.     pid = ourwait(&w.w_status);
  284. #  else    /* SVID >= 3 */
  285.     /* 
  286.      * XXX: for greater than 3 we should use waitpid(). 
  287.      * but then again, SVR4 falls into the POSIX/BSDJOBS category.
  288.      */
  289.     pid = wait(&w.w_status);
  290. #  endif /* SVID >= 3 */
  291. # endif    /* BSDTIMES */
  292. # ifndef BSDSIGS
  293.     (void) sigset(SIGCHLD, pchild);
  294. # endif /* !BSDSIGS */
  295. #endif /* BSDJOBS */
  296.  
  297. #ifdef JOBDEBUG
  298.     {
  299.     char    buffer[100];
  300.     xsprintf(buffer, "pid %d, retval %x termsig %x retcode %x\n",
  301.          pid, w, WTERMSIG(w), WEXITSTATUS(w));
  302.     xprintf(buffer);
  303.     flush();
  304.     }
  305. #endif /* JOBDEBUG */
  306.  
  307.     if (pid <= 0) {
  308. #ifdef JOBDEBUG
  309.     xprintf("errno == %d\n", errno);
  310. #endif
  311.     if (errno == EINTR) {
  312.         errno = 0;
  313.         goto loop;
  314.     }
  315.     pnoprocesses = pid == -1;
  316. #ifndef SIGVOID
  317.     return (0);
  318. #else /* !SIGVOID */
  319.     return;
  320. #endif /* SIGVOID */
  321.     }
  322.     for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next)
  323.     if (pid == pp->p_pid)
  324.         goto found;
  325. #ifndef BSDJOBS
  326.     /* this should never have happened */
  327.     stderror(ERR_SYNC, pid);
  328.     xexit(0);
  329. #else /* BSDJOBS */
  330.     goto loop;
  331. #endif /* BSDJOBS */
  332. found:
  333.     if (pid == atoi(short2str(value(STRchild))))
  334.     unsetv(STRchild);
  335.     pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);
  336.     if (WIFSTOPPED(w)) {
  337.     pp->p_flags |= PSTOPPED;
  338.     pp->p_reason = WSTOPSIG(w);
  339.     }
  340.     else {
  341.     if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))
  342. #ifndef BSDTIMES
  343. # ifdef _SEQUENT_
  344.         (void) get_process_stats(&pp->p_etime, PS_SELF, NULL, NULL);
  345. # else    /* !_SEQUENT_ */
  346.         pp->p_etime = times(&proctimes);
  347. # endif    /* !_SEQUENT_ */
  348. #else /* BSDTIMES */
  349.         (void) gettimeofday(&pp->p_etime, NULL);
  350. #endif /* BSDTIMES */
  351.  
  352.  
  353. #if defined(BSDTIMES) || defined(_SEQUENT_)
  354.     pp->p_rusage = ru;
  355. #else /* !BSDTIMES && !_SEQUENT_ */
  356.     (void) times(&proctimes);
  357.     pp->p_utime = proctimes.tms_cutime - shtimes.tms_cutime;
  358.     pp->p_stime = proctimes.tms_cstime - shtimes.tms_cstime;
  359.     shtimes = proctimes;
  360. #endif /* !BSDTIMES && !_SEQUENT_ */
  361.     if (WIFSIGNALED(w)) {
  362.         if (WTERMSIG(w) == SIGINT)
  363.         pp->p_flags |= PINTERRUPTED;
  364.         else
  365.         pp->p_flags |= PSIGNALED;
  366.         if (WCOREDUMP(w))
  367.         pp->p_flags |= PDUMPED;
  368.         pp->p_reason = WTERMSIG(w);
  369.     }
  370.     else {
  371.         pp->p_reason = WEXITSTATUS(w);
  372.         if (pp->p_reason != 0)
  373.         pp->p_flags |= PAEXITED;
  374.         else
  375.         pp->p_flags |= PNEXITED;
  376.     }
  377.     }
  378.     jobflags = 0;
  379.     fp = pp;
  380.     do {
  381.     if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&
  382.         !child && adrof(STRtime) &&
  383. #ifdef BSDTIMES
  384.         fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
  385. #else /* !BSDTIMES */
  386. # ifdef _SEQUENT_
  387.         fp->p_rusage.ps_utime.tv_sec + fp->p_rusage.ps_stime.tv_sec
  388. # else /* !_SEQUENT_ */
  389. #  ifndef POSIX
  390.         (fp->p_utime + fp->p_stime) / HZ
  391. #  else /* POSIX */
  392.         (fp->p_utime + fp->p_stime) / CLK_TCK
  393. #  endif /* POSIX */
  394. # endif /* !_SEQUENT_ */
  395. #endif /* !BSDTIMES */
  396.         >= atoi(short2str(value(STRtime))))
  397.         fp->p_flags |= PTIME;
  398.     jobflags |= fp->p_flags;
  399.     } while ((fp = fp->p_friends) != pp);
  400.     pp->p_flags &= ~PFOREGND;
  401.     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
  402.     pp->p_flags &= ~PPTIME;
  403.     pp->p_flags |= PTIME;
  404.     }
  405.     if ((jobflags & (PRUNNING | PREPORTED)) == 0) {
  406.     fp = pp;
  407.     do {
  408.         if (fp->p_flags & PSTOPPED)
  409.         fp->p_flags |= PREPORTED;
  410.     } while ((fp = fp->p_friends) != pp);
  411.     while (fp->p_pid != fp->p_jobid)
  412.         fp = fp->p_friends;
  413.     if (jobflags & PSTOPPED) {
  414.         if (pcurrent && pcurrent != fp)
  415.         pprevious = pcurrent;
  416.         pcurrent = fp;
  417.     }
  418.     else
  419.         pclrcurr(fp);
  420.     if (jobflags & PFOREGND) {
  421.         if (jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||
  422. #ifdef IIASA
  423.         jobflags & PAEXITED ||
  424. #endif /* IIASA */
  425.         !eq(dcwd->di_name, fp->p_cwd->di_name)) {
  426.         ;        /* print in pjwait */
  427.         }
  428.         /* PWP: print a newline after ^C */
  429.         else if (jobflags & PINTERRUPTED)
  430. #ifdef SHORT_STRINGS
  431.         xputchar('\r' | QUOTE), xputchar('\n');
  432. #else /* !SHORT_STRINGS */
  433.         xprintf("\215\n");    /* \215 is a quoted ^M */
  434. #endif /* !SHORT_STRINGS */
  435. #ifdef notdef
  436.         else if ((jobflags & (PTIME|PSTOPPED)) == PTIME)
  437.                 ptprint(fp);
  438. #endif
  439.     }
  440.     else {
  441.         if (jobflags & PNOTIFY || adrof(STRnotify)) {
  442. #ifdef SHORT_STRINGS
  443.         xputchar('\r' | QUOTE), xputchar('\n');
  444. #else /* !SHORT_STRINGS */
  445.         xprintf("\215\n");    /* \215 is a quoted ^M */
  446. #endif /* !SHORT_STRINGS */
  447.         (void) pprint(pp, NUMBER | NAME | REASON);
  448.         if ((jobflags & PSTOPPED) == 0)
  449.             pflush(pp);
  450.         {
  451.             extern Char GettingInput;
  452.  
  453.             if (GettingInput) {
  454.             errno = 0;
  455.             (void) Rawmode();
  456.             ClearLines();
  457.             ClearDisp();
  458.             Refresh();
  459.             }
  460.         }
  461.         }
  462.         else {
  463.         fp->p_flags |= PNEEDNOTE;
  464.         neednote++;
  465.         }
  466.     }
  467.     }
  468. #ifdef BSDJOBS
  469.     goto loop;
  470. #endif /* BSDJOBS */
  471. }
  472.  
  473. void
  474. pnote()
  475. {
  476.     register struct process *pp;
  477.     int     flags;
  478. #ifdef BSDSIGS
  479.     sigmask_t omask;
  480. #endif /* BSDSIGS */
  481.  
  482.     neednote = 0;
  483.     for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next) {
  484.     if (pp->p_flags & PNEEDNOTE) {
  485. #ifdef BSDSIGS
  486.         omask = sigblock(sigmask(SIGCHLD));
  487. #else /* !BSDSIGS */
  488.         (void) sighold(SIGCHLD);
  489. #endif /* !BSDSIGS */
  490.         pp->p_flags &= ~PNEEDNOTE;
  491.         flags = pprint(pp, NUMBER | NAME | REASON);
  492.         if ((flags & (PRUNNING | PSTOPPED)) == 0)
  493.         pflush(pp);
  494. #ifdef BSDSIGS
  495.         (void) sigsetmask(omask);
  496. #else /* !BSDSIGS */
  497.         (void) sigrelse(SIGCHLD);
  498. #endif /* !BSDSIGS */
  499.     }
  500.     }
  501. }
  502.  
  503. /*
  504.  * pwait - wait for current job to terminate, maintaining integrity
  505.  *    of current and previous job indicators.
  506.  */
  507. void
  508. pwait()
  509. {
  510.     register struct process *fp, *pp;
  511. #ifdef BSDSIGS
  512.     sigmask_t omask;
  513. #endif /* BSDSIGS */
  514.  
  515.     /*
  516.      * Here's where dead procs get flushed.
  517.      */
  518. #ifdef BSDSIGS
  519.     omask = sigblock(sigmask(SIGCHLD));
  520. #else /* !BSDSIGS */
  521.     (void) sighold(SIGCHLD);
  522. #endif /* !BSDSIGS */
  523.     for (pp = (fp = &proclist)->p_next; pp != PNULL; pp = (fp = pp)->p_next)
  524.     if (pp->p_pid == 0) {
  525.         fp->p_next = pp->p_next;
  526.         xfree((ptr_t) pp->p_command);
  527.         if (pp->p_cwd && --pp->p_cwd->di_count == 0)
  528.         if (pp->p_cwd->di_next == 0)
  529.             dfree(pp->p_cwd);
  530.         xfree((ptr_t) pp);
  531.         pp = fp;
  532.     }
  533. #ifdef BSDSIGS
  534.     (void) sigsetmask(omask);
  535. #else /* !BSDSIGS */
  536.     (void) sigrelse(SIGCHLD);
  537. # ifdef notdef
  538.     if (setintr)
  539.     sigignore(SIGINT);
  540. # endif
  541. #endif /* !BSDSIGS */
  542.     pjwait(pcurrjob);
  543. }
  544.  
  545.  
  546. /*
  547.  * pjwait - wait for a job to finish or become stopped
  548.  *    It is assumed to be in the foreground state (PFOREGND)
  549.  */
  550. void
  551. pjwait(pp)
  552.     register struct process *pp;
  553. {
  554.     register struct process *fp;
  555.     int     jobflags, reason;
  556. #ifdef BSDSIGS
  557.     sigmask_t omask;
  558. #endif /* BSDSIGS */
  559. #if (SVID > 0) && (SVID < 3)
  560.     sigret_t (*inthandler)();
  561. #endif /* (SVID > 0) && (SVID < 3) */
  562.  
  563.     while (pp->p_pid != pp->p_jobid)
  564.     pp = pp->p_friends;
  565.     fp = pp;
  566.  
  567.     do {
  568.     if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
  569.         xprintf("BUG: waiting for background job!\n");
  570.     } while ((fp = fp->p_friends) != pp);
  571.     /*
  572.      * Now keep pausing as long as we are not interrupted (SIGINT), and the
  573.      * target process, or any of its friends, are running
  574.      */
  575.     fp = pp;
  576. #ifdef BSDSIGS
  577.     omask = sigblock(sigmask(SIGCHLD));
  578. #endif /* BSDSIGS */
  579. #if (SVID > 0) && (SVID < 3)
  580.     if (setintr)
  581.         inthandler = signal(SIGINT, SIG_IGN);
  582. #endif /* (SVID > 0) && (SVID < 3) */
  583.     for (;;) {
  584. #ifndef BSDSIGS
  585.     (void) sighold(SIGCHLD);
  586. #endif /* !BSDSIGS */
  587.     jobflags = 0;
  588.     do
  589.         jobflags |= fp->p_flags;
  590.     while ((fp = (fp->p_friends)) != pp);
  591.     if ((jobflags & PRUNNING) == 0)
  592.         break;
  593. #ifdef JOBDEBUG
  594.     xprintf("starting to sigpause for  SIGCHLD on %d\n", fp->p_pid);
  595. #endif /* JOBDEBUG */
  596. #ifdef BSDSIGS
  597.     /* sigpause(sigblock((sigmask_t) 0) &~ sigmask(SIGCHLD)); */
  598.     (void) sigpause(omask & ~sigmask(SIGCHLD));
  599. #else /* !BSDSIGS */
  600.     (void) sigpause(SIGCHLD);
  601. #endif /* !BSDSIGS */
  602.     }
  603. #ifdef BSDSIGS
  604.     (void) sigsetmask(omask);
  605. #else /* !BSDSIGS */
  606.     (void) sigrelse(SIGCHLD);
  607. #endif /* !BSDSIGS */
  608. #if (SVID > 0) && (SVID < 3)
  609.     if (setintr)
  610.         (void) signal(SIGINT, inthandler);
  611. #endif /* (SVID > 0) && (SVID < 3) */
  612. #ifdef BSDJOBS
  613.     if (tpgrp > 0)        /* get tty back */
  614.     (void) tcsetpgrp(FSHTTY, tpgrp);
  615. #endif /* BSDJOBS */
  616.     if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
  617.     !eq(dcwd->di_name, fp->p_cwd->di_name)) {
  618.     if (jobflags & PSTOPPED) {
  619.         xprintf("\n");
  620.         if (adrof(STRlistjobs)) {
  621.         Char   *jobcommand[3];
  622.  
  623.         jobcommand[0] = STRjobs;
  624.         if (eq(value(STRlistjobs), STRlong))
  625.             jobcommand[1] = STRml;
  626.         else
  627.             jobcommand[1] = NULL;
  628.         jobcommand[2] = NULL;
  629.  
  630.         dojobs(jobcommand, NULL);
  631.         (void) pprint(pp, SHELLDIR);
  632.         }
  633.         else
  634.         (void) pprint(pp, AREASON | SHELLDIR);
  635.     }
  636.     else
  637.         (void) pprint(pp, AREASON | SHELLDIR);
  638.     }
  639.     if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
  640.     (!gointr || !eq(gointr, STRminus))) {
  641.     if ((jobflags & PSTOPPED) == 0)
  642.         pflush(pp);
  643.     pintr1(0);
  644.     /* NOTREACHED */
  645.     }
  646.     reason = 0;
  647.     fp = pp;
  648.     do {
  649.     if (fp->p_reason)
  650.         reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
  651.         fp->p_reason | META : fp->p_reason;
  652.     } while ((fp = fp->p_friends) != pp);
  653.     if ((reason != 0) && (adrof(STRprintexitvalue)))    /* PWP */
  654.     xprintf("Exit %d\n", reason);
  655.     set(STRstatus, putn(reason));
  656.     if (reason && exiterr)
  657.     exitstat();
  658.     pflush(pp);
  659. }
  660.  
  661. /*
  662.  * dowait - wait for all processes to finish
  663.  */
  664.  
  665. /*ARGSUSED*/
  666. void
  667. dowait(v, c)
  668.     Char **v;
  669.     struct command *c;
  670. {
  671.     register struct process *pp;
  672. #ifdef BSDSIGS
  673.     sigmask_t omask;
  674. #endif /* BSDSIGS */
  675.  
  676.     pjobs++;
  677. #ifdef BSDSIGS
  678.     omask = sigblock(sigmask(SIGCHLD));
  679. loop:
  680. #else /* !BSDSIGS */
  681.     if (setintr)
  682.     (void) sigrelse(SIGINT);
  683. loop:
  684.     (void) sighold(SIGCHLD);
  685. #endif /* !BSDSIGS */
  686.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  687.     if (pp->p_pid &&    /* pp->p_pid == pp->p_jobid && */
  688.         pp->p_flags & PRUNNING) {
  689. #ifdef BSDSIGS
  690.         (void) sigpause((sigmask_t) 0);
  691. #else /* !BSDSIGS */
  692.         (void) sigpause(SIGCHLD);
  693. #endif /* !BSDSIGS */
  694.         goto loop;
  695.     }
  696. #ifdef BSDSIGS
  697.     (void) sigsetmask(omask);
  698. #else /* !BSDSIGS */
  699.     (void) sigrelse(SIGCHLD);
  700. #endif /* !BSDSIGS */
  701.     pjobs = 0;
  702. }
  703.  
  704. /*
  705.  * pflushall - flush all jobs from list (e.g. at fork())
  706.  */
  707. static void
  708. pflushall()
  709. {
  710.     register struct process *pp;
  711.  
  712.     for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next)
  713.     if (pp->p_pid)
  714.         pflush(pp);
  715. }
  716.  
  717. /*
  718.  * pflush - flag all process structures in the same job as the
  719.  *    the argument process for deletion.  The actual free of the
  720.  *    space is not done here since pflush is called at interrupt level.
  721.  */
  722. static void
  723. pflush(pp)
  724.     register struct process *pp;
  725. {
  726.     register struct process *np;
  727.     register int idx;
  728.  
  729.     if (pp->p_pid == 0) {
  730.     xprintf("BUG: process flushed twice");
  731.     return;
  732.     }
  733.     while (pp->p_pid != pp->p_jobid)
  734.     pp = pp->p_friends;
  735.     pclrcurr(pp);
  736.     if (pp == pcurrjob)
  737.     pcurrjob = 0;
  738.     idx = pp->p_index;
  739.     np = pp;
  740.     do {
  741.     np->p_index = np->p_pid = 0;
  742.     np->p_flags &= ~PNEEDNOTE;
  743.     } while ((np = np->p_friends) != pp);
  744.     if (idx == pmaxindex) {
  745.     for (np = proclist.p_next, idx = 0; np; np = np->p_next)
  746.         if (np->p_index > idx)
  747.         idx = np->p_index;
  748.     pmaxindex = idx;
  749.     }
  750. }
  751.  
  752. /*
  753.  * pclrcurr - make sure the given job is not the current or previous job;
  754.  *    pp MUST be the job leader
  755.  */
  756. static void
  757. pclrcurr(pp)
  758.     register struct process *pp;
  759. {
  760.     if (pp == pcurrent)
  761.     if (pprevious != PNULL) {
  762.         pcurrent = pprevious;
  763.         pprevious = pgetcurr(pp);
  764.     }
  765.     else {
  766.         pcurrent = pgetcurr(pp);
  767.         pprevious = pgetcurr(pp);
  768.     }
  769.     else if (pp == pprevious)
  770.     pprevious = pgetcurr(pp);
  771. }
  772.  
  773. /* +4 here is 1 for '\0', 1 ea for << >& >> */
  774. static Char command[PMAXLEN + 4];
  775. static int cmdlen;
  776. static Char *cmdp;
  777.  
  778. /*
  779.  * palloc - allocate a process structure and fill it up.
  780.  *    an important assumption is made that the process is running.
  781.  */
  782. void
  783. palloc(pid, t)
  784.     int     pid;
  785.     register struct command *t;
  786. {
  787.     register struct process *pp;
  788.     int     i;
  789.  
  790.     pp = (struct process *) xcalloc(1, (size_t) sizeof(struct process));
  791.     pp->p_pid = pid;
  792.     pp->p_flags = t->t_dflg & F_AMPERSAND ? PRUNNING : PRUNNING | PFOREGND;
  793.     if (t->t_dflg & F_TIME)
  794.     pp->p_flags |= PPTIME;
  795.     cmdp = command;
  796.     cmdlen = 0;
  797.     padd(t);
  798.     *cmdp++ = 0;
  799.     if (t->t_dflg & F_PIPEOUT) {
  800.     pp->p_flags |= PPOU;
  801.     if (t->t_dflg & F_STDERR)
  802.         pp->p_flags |= PDIAG;
  803.     }
  804.     pp->p_command = Strsave(command);
  805.     if (pcurrjob) {
  806.     struct process *fp;
  807.  
  808.     /* careful here with interrupt level */
  809.     pp->p_cwd = 0;
  810.     pp->p_index = pcurrjob->p_index;
  811.     pp->p_friends = pcurrjob;
  812.     pp->p_jobid = pcurrjob->p_pid;
  813.     for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends);
  814.     fp->p_friends = pp;
  815.     }
  816.     else {
  817.     pcurrjob = pp;
  818.     pp->p_jobid = pid;
  819.     pp->p_friends = pp;
  820.     pp->p_cwd = dcwd;
  821.     dcwd->di_count++;
  822.     if (pmaxindex < BIGINDEX)
  823.         pp->p_index = ++pmaxindex;
  824.     else {
  825.         struct process *np;
  826.  
  827.         for (i = 1;; i++) {
  828.         for (np = proclist.p_next; np; np = np->p_next)
  829.             if (np->p_index == i)
  830.             goto tryagain;
  831.         pp->p_index = i;
  832.         if (i > pmaxindex)
  833.             pmaxindex = i;
  834.         break;
  835.     tryagain:;
  836.         }
  837.     }
  838.     if (pcurrent == PNULL)
  839.         pcurrent = pp;
  840.     else if (pprevious == PNULL)
  841.         pprevious = pp;
  842.     }
  843.     pp->p_next = proclist.p_next;
  844.     proclist.p_next = pp;
  845. #ifdef BSDTIMES
  846.     (void) gettimeofday(&pp->p_btime, NULL);
  847. #else /* !BSDTIMES */
  848. # ifdef _SEQUENT_
  849.     (void) get_process_stats(&pp->p_btime, PS_SELF, NULL, NULL);
  850. # else /* !_SEQUENT_ */
  851.     {
  852.     struct tms tmptimes;
  853.  
  854.     pp->p_btime = times(&tmptimes);
  855.     }
  856. # endif /* !_SEQUENT_ */
  857. #endif /* !BSDTIMES */
  858. }
  859.  
  860. static void
  861. padd(t)
  862.     register struct command *t;
  863. {
  864.     Char  **argp;
  865.  
  866.     if (t == 0)
  867.     return;
  868.     switch (t->t_dtyp) {
  869.  
  870.     case NODE_PAREN:
  871.     pads(STRLparensp);
  872.     padd(t->t_dspr);
  873.     pads(STRspRparen);
  874.     break;
  875.  
  876.     case NODE_COMMAND:
  877.     for (argp = t->t_dcom; *argp; argp++) {
  878.         pads(*argp);
  879.         if (argp[1])
  880.         pads(STRspace);
  881.     }
  882.     break;
  883.  
  884.     case NODE_OR:
  885.     case NODE_AND:
  886.     case NODE_PIPE:
  887.     case NODE_LIST:
  888.     padd(t->t_dcar);
  889.     switch (t->t_dtyp) {
  890.     case NODE_OR:
  891.         pads(STRspor2sp);
  892.         break;
  893.     case NODE_AND:
  894.         pads(STRspand2sp);
  895.         break;
  896.     case NODE_PIPE:
  897.         pads(STRsporsp);
  898.         break;
  899.     case NODE_LIST:
  900.         pads(STRsemisp);
  901.         break;
  902.     }
  903.     padd(t->t_dcdr);
  904.     return;
  905.     }
  906.     if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
  907.     pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp);
  908.     pads(t->t_dlef);
  909.     }
  910.     if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
  911.     pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow);
  912.     if (t->t_dflg & F_STDERR)
  913.         pads(STRand);
  914.     pads(STRspace);
  915.     pads(t->t_drit);
  916.     }
  917. }
  918.  
  919. static void
  920. pads(cp)
  921.     Char   *cp;
  922. {
  923.     register int i;
  924.  
  925.     /*
  926.      * Avoid the Quoted Space alias hack! Reported by:
  927.      * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks)
  928.      */
  929.     if (cp[0] == STRQNULL[0])
  930.     cp++;
  931.  
  932.     i = Strlen(cp);
  933.  
  934.     if (cmdlen >= PMAXLEN)
  935.     return;
  936.     if (cmdlen + i >= PMAXLEN) {
  937.     (void) Strcpy(cmdp, STRsp3dots);
  938.     cmdlen = PMAXLEN;
  939.     cmdp += 4;
  940.     return;
  941.     }
  942.     (void) Strcpy(cmdp, cp);
  943.     cmdp += i;
  944.     cmdlen += i;
  945. }
  946.  
  947. /*
  948.  * psavejob - temporarily save the current job on a one level stack
  949.  *    so another job can be created.  Used for { } in exp6
  950.  *    and `` in globbing.
  951.  */
  952. void
  953. psavejob()
  954. {
  955.     pholdjob = pcurrjob;
  956.     pcurrjob = PNULL;
  957. }
  958.  
  959. /*
  960.  * prestjob - opposite of psavejob.  This may be missed if we are interrupted
  961.  *    somewhere, but pendjob cleans up anyway.
  962.  */
  963. void
  964. prestjob()
  965. {
  966.     pcurrjob = pholdjob;
  967.     pholdjob = PNULL;
  968. }
  969.  
  970. /*
  971.  * pendjob - indicate that a job (set of commands) has been completed
  972.  *    or is about to begin.
  973.  */
  974. void
  975. pendjob()
  976. {
  977.     register struct process *pp, *tp;
  978.  
  979.     if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) {
  980.     pp = pcurrjob;
  981.     while (pp->p_pid != pp->p_jobid)
  982.         pp = pp->p_friends;
  983.     xprintf("[%d]", pp->p_index);
  984.     tp = pp;
  985.     do {
  986.         xprintf(" %d", pp->p_pid);
  987.         pp = pp->p_friends;
  988.     } while (pp != tp);
  989.     xprintf("\n");
  990.     }
  991.     pholdjob = pcurrjob = 0;
  992. }
  993.  
  994. /*
  995.  * pprint - print a job
  996.  */
  997. static int
  998. pprint(pp, flag)
  999.     register struct process *pp;
  1000.     bool    flag;
  1001. {
  1002.     register status, reason;
  1003.     struct process *tp;
  1004.     extern char *linp, linbuf[];
  1005.     int     jobflags, pstatus;
  1006.     char   *format;
  1007.  
  1008.     while (pp->p_pid != pp->p_jobid)
  1009.     pp = pp->p_friends;
  1010.     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
  1011.     pp->p_flags &= ~PPTIME;
  1012.     pp->p_flags |= PTIME;
  1013.     }
  1014.     tp = pp;
  1015.     status = reason = -1;
  1016.     jobflags = 0;
  1017.     do {
  1018.     jobflags |= pp->p_flags;
  1019.     pstatus = pp->p_flags & PALLSTATES;
  1020.     if (tp != pp && linp != linbuf && !(flag & FANCY) &&
  1021.         (pstatus == status && pp->p_reason == reason ||
  1022.          !(flag & REASON)))
  1023.         xprintf(" ");
  1024.     else {
  1025.         if (tp != pp && linp != linbuf)
  1026.         xprintf("\n");
  1027.         if (flag & NUMBER)
  1028.         if (pp == tp)
  1029.             xprintf("[%d]%s %c ", pp->p_index,
  1030.                 pp->p_index < 10 ? " " : "",
  1031.                 pp == pcurrent ? '+' :
  1032.                 (pp == pprevious ? '-' : ' '));
  1033.         else
  1034.             xprintf("       ");
  1035.         if (flag & FANCY) {
  1036. #ifdef TCF
  1037.         extern char *sitename();
  1038.  
  1039. #endif /* TCF */
  1040.         xprintf("%5d ", pp->p_pid);
  1041. #ifdef TCF
  1042.         xprintf("%11s ", sitename(pp->p_pid));
  1043. #endif /* TCF */
  1044.         }
  1045.         if (flag & (REASON | AREASON)) {
  1046.         if (flag & NAME)
  1047. #ifdef SUSPENDED
  1048.             format = "%-23s";
  1049. #else /* !SUSPENDED */
  1050.             format = "%-21s";
  1051. #endif /* !SUSPENDED */
  1052.         else
  1053.             format = "%s";
  1054.         if (pstatus == status)
  1055.             if (pp->p_reason == reason) {
  1056.             xprintf(format, "");
  1057.             goto prcomd;
  1058.             }
  1059.             else
  1060.             reason = pp->p_reason;
  1061.         else {
  1062.             status = pstatus;
  1063.             reason = pp->p_reason;
  1064.         }
  1065.         switch (status) {
  1066.  
  1067.         case PRUNNING:
  1068.             xprintf(format, "Running ");
  1069.             break;
  1070.  
  1071.         case PINTERRUPTED:
  1072.         case PSTOPPED:
  1073.         case PSIGNALED:
  1074.             /*
  1075.              * tell what happened to the background job
  1076.              * From: Michael Schroeder 
  1077.              * <mlschroe@immd4.informatik.uni-erlangen.de>
  1078.              */
  1079.             if ((flag & REASON)
  1080.             || ((flag & AREASON)
  1081.                 && reason != SIGINT
  1082.                 && (reason != SIGPIPE
  1083.                 || (pp->p_flags & PPOU) == 0)))
  1084.             xprintf(format, mesg[pp->p_reason & ASCII].pname);
  1085.             else
  1086.             reason = -1;
  1087.             break;
  1088.  
  1089.         case PNEXITED:
  1090.         case PAEXITED:
  1091.             if (flag & REASON)
  1092.             if (pp->p_reason)
  1093. #ifdef SUSPENDED
  1094.                 xprintf("Exit %-18d", pp->p_reason);
  1095. #else /* SUSPENDED */
  1096.                 xprintf("Exit %-16d", pp->p_reason);
  1097. #endif /* SUSPENDED */
  1098.             else
  1099.                 xprintf(format, "Done");
  1100.             break;
  1101.  
  1102.         default:
  1103.             xprintf("BUG: status=%-9o", status);
  1104.         }
  1105.         }
  1106.     }
  1107. prcomd:
  1108.     if (flag & NAME) {
  1109.         xprintf("%s", short2str(pp->p_command));
  1110.         if (pp->p_flags & PPOU)
  1111.         xprintf(" |");
  1112.         if (pp->p_flags & PDIAG)
  1113.         xprintf("&");
  1114.     }
  1115.     if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED)
  1116.         xprintf(" (core dumped)");
  1117.     if (tp == pp->p_friends) {
  1118.         if (flag & AMPERSAND)
  1119.         xprintf(" &");
  1120.         if (flag & JOBDIR &&
  1121.         !eq(tp->p_cwd->di_name, dcwd->di_name)) {
  1122.         xprintf(" (wd: ");
  1123.         dtildepr(value(STRhome), tp->p_cwd->di_name);
  1124.         xprintf(")");
  1125.         }
  1126.     }
  1127.     if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
  1128.         if (linp != linbuf)
  1129.         xprintf("\n\t");
  1130. #if defined(BSDTIMES) || defined(_SEQUENT_)
  1131.         prusage(&zru, &pp->p_rusage, &pp->p_etime,
  1132.             &pp->p_btime);
  1133. #else /* !BSDTIMES && !SEQUENT */
  1134.         lru.tms_utime = pp->p_utime;
  1135.         lru.tms_stime = pp->p_stime;
  1136.         lru.tms_cutime = 0;
  1137.         lru.tms_cstime = 0;
  1138.         prusage(&zru, &lru, pp->p_etime,
  1139.             pp->p_btime);
  1140. #endif /* !BSDTIMES && !SEQUENT */
  1141.  
  1142.     }
  1143.     if (tp == pp->p_friends) {
  1144.         if (linp != linbuf)
  1145.         xprintf("\n");
  1146.         if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
  1147.         xprintf("(wd now: ");
  1148.         dtildepr(value(STRhome), dcwd->di_name);
  1149.         xprintf(")\n");
  1150.         }
  1151.     }
  1152.     } while ((pp = pp->p_friends) != tp);
  1153.     if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
  1154.     if (jobflags & NUMBER)
  1155.         xprintf("       ");
  1156.     ptprint(tp);
  1157.     }
  1158.     return (jobflags);
  1159. }
  1160.  
  1161. static void
  1162. ptprint(tp)
  1163.     register struct process *tp;
  1164. {
  1165. #ifdef BSDTIMES
  1166.     struct timeval tetime, diff;
  1167.     static struct timeval ztime;
  1168.     struct rusage ru;
  1169.     static struct rusage zru;
  1170.     register struct process *pp = tp;
  1171.  
  1172.     ru = zru;
  1173.     tetime = ztime;
  1174.     do {
  1175.     ruadd(&ru, &pp->p_rusage);
  1176.     tvsub(&diff, &pp->p_etime, &pp->p_btime);
  1177.     if (timercmp(&diff, &tetime, >))
  1178.         tetime = diff;
  1179.     } while ((pp = pp->p_friends) != tp);
  1180.     prusage(&zru, &ru, &tetime, &ztime);
  1181. #else /* !BSDTIMES */
  1182. # ifdef _SEQUENT_
  1183. #  define timercmp(tvp, uvp, cmp) \
  1184.       ((tvp)->tv_sec cmp (uvp)->tv_sec || \
  1185.        (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)
  1186.     timeval_t tetime, diff;
  1187.     static timeval_t ztime;
  1188.     struct process_stats ru;
  1189.     static struct process_stats zru;
  1190.     register struct process *pp = tp;
  1191.  
  1192.     ru = zru;
  1193.     tetime = ztime;
  1194.     do {
  1195.     ruadd(&ru, &pp->p_rusage);
  1196.     tvsub(&diff, &pp->p_etime, &pp->p_btime);
  1197.     if (timercmp(&diff, &tetime, >))
  1198.         tetime = diff;
  1199.     } while ((pp = pp->p_friends) != tp);
  1200.     prusage(&zru, &ru, &tetime, &ztime);
  1201. # else /* !_SEQUENT_ */
  1202. #  ifndef POSIX
  1203.     static time_t ztime = 0;
  1204.     static time_t zu_time = 0;
  1205.     static time_t zs_time = 0;
  1206.     time_t  tetime, diff;
  1207.     time_t  u_time, s_time;
  1208.  
  1209. #  else    /* POSIX */
  1210.     static clock_t ztime = 0;
  1211.     static clock_t zu_time = 0;
  1212.     static clock_t zs_time = 0;
  1213.     clock_t tetime, diff;
  1214.     clock_t u_time, s_time;
  1215.  
  1216. #  endif /* POSIX */
  1217.     struct tms zts, rts;
  1218.     register struct process *pp = tp;
  1219.  
  1220.     u_time = zu_time;
  1221.     s_time = zs_time;
  1222.     tetime = ztime;
  1223.     do {
  1224.     u_time += pp->p_utime;
  1225.     s_time += pp->p_stime;
  1226.     diff = pp->p_etime - pp->p_btime;
  1227.     if (diff > tetime)
  1228.         tetime = diff;
  1229.     } while ((pp = pp->p_friends) != tp);
  1230.     zts.tms_utime = zu_time;
  1231.     zts.tms_stime = zs_time;
  1232.     zts.tms_cutime = 0;
  1233.     zts.tms_cstime = 0;
  1234.     rts.tms_utime = u_time;
  1235.     rts.tms_stime = s_time;
  1236.     rts.tms_cutime = 0;
  1237.     rts.tms_cstime = 0;
  1238.     prusage(&zts, &rts, tetime, ztime);
  1239. # endif /* !_SEQUENT_ */
  1240. #endif    /* !BSDTIMES */
  1241. }
  1242.  
  1243. /*
  1244.  * dojobs - print all jobs
  1245.  */
  1246. /*ARGSUSED*/
  1247. void
  1248. dojobs(v, c)
  1249.     Char  **v;
  1250.     struct command *c;
  1251. {
  1252.     register struct process *pp;
  1253.     register int flag = NUMBER | NAME | REASON;
  1254.     int     i;
  1255.  
  1256.     if (chkstop)
  1257.     chkstop = 2;
  1258.     if (*++v) {
  1259.     if (v[1] || !eq(*v, STRml))
  1260.         stderror(ERR_JOBS);
  1261.     flag |= FANCY | JOBDIR;
  1262.     }
  1263.     for (i = 1; i <= pmaxindex; i++)
  1264.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  1265.         if (pp->p_index == i && pp->p_pid == pp->p_jobid) {
  1266.         pp->p_flags &= ~PNEEDNOTE;
  1267.         if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
  1268.             pflush(pp);
  1269.         break;
  1270.         }
  1271. }
  1272.  
  1273. /*
  1274.  * dofg - builtin - put the job into the foreground
  1275.  */
  1276. /*ARGSUSED*/
  1277. void
  1278. dofg(v, c)
  1279.     Char  **v;
  1280.     struct command *c;
  1281. {
  1282.     register struct process *pp;
  1283.  
  1284.     okpcntl();
  1285.     ++v;
  1286.     do {
  1287.     pp = pfind(*v);
  1288.     pstart(pp, 1);
  1289. #ifndef BSDSIGS
  1290. # ifdef notdef
  1291.     if (setintr)
  1292.         sigignore(SIGINT);
  1293. # endif
  1294. #endif /* !BSDSIGS */
  1295.     pjwait(pp);
  1296.     } while (*v && *++v);
  1297. }
  1298.  
  1299. /*
  1300.  * %... - builtin - put the job into the foreground
  1301.  */
  1302. /*ARGSUSED*/
  1303. void
  1304. dofg1(v, c)
  1305.     Char  **v;
  1306.     struct command *c;
  1307. {
  1308.     register struct process *pp;
  1309.  
  1310.     okpcntl();
  1311.     pp = pfind(v[0]);
  1312.     pstart(pp, 1);
  1313. #ifndef BSDSIGS
  1314. # ifdef notdef
  1315.     if (setintr)
  1316.     sigignore(SIGINT);
  1317. # endif
  1318. #endif /* !BSDSIGS */
  1319.     pjwait(pp);
  1320. }
  1321.  
  1322. /*
  1323.  * dobg - builtin - put the job into the background
  1324.  */
  1325. /*ARGSUSED*/
  1326. void
  1327. dobg(v, c)
  1328.     Char  **v;
  1329.     struct command *c;
  1330. {
  1331.     register struct process *pp;
  1332.  
  1333.     okpcntl();
  1334.     ++v;
  1335.     do {
  1336.     pp = pfind(*v);
  1337.     pstart(pp, 0);
  1338.     } while (*v && *++v);
  1339. }
  1340.  
  1341. /*
  1342.  * %... & - builtin - put the job into the background
  1343.  */
  1344. /*ARGSUSED*/
  1345. void
  1346. dobg1(v, c)
  1347.     Char  **v;
  1348.     struct command *c;
  1349. {
  1350.     register struct process *pp;
  1351.  
  1352.     pp = pfind(v[0]);
  1353.     pstart(pp, 0);
  1354. }
  1355.  
  1356. /*
  1357.  * dostop - builtin - stop the job
  1358.  */
  1359. /*ARGSUSED*/
  1360. void
  1361. dostop(v, c)
  1362.     Char  **v;
  1363.     struct command *c;
  1364. {
  1365. #ifdef BSDJOBS
  1366.     pkill(++v, SIGSTOP);
  1367. #endif /* BSDJOBS */
  1368. }
  1369.  
  1370. /*
  1371.  * dokill - builtin - superset of kill (1)
  1372.  */
  1373. /*ARGSUSED*/
  1374. void
  1375. dokill(v, c)
  1376.     Char  **v;
  1377.     struct command *c;
  1378. {
  1379.     register int signum, len = 0;
  1380.     register char *name;
  1381.     extern int T_Cols;
  1382.  
  1383.     v++;
  1384.     if (v[0] && v[0][0] == '-') {
  1385.     if (v[0][1] == 'l') {
  1386.         for (signum = 1; signum <= NSIG; signum++) {
  1387.         if ((name = mesg[signum].iname) != NULL) {
  1388.             len += strlen(name) + 1;
  1389.             if (len >= T_Cols - 1) {
  1390.             xprintf("\n");
  1391.             len = strlen(name) + 1;
  1392.             }
  1393.             xprintf("%s ", name);
  1394.         }
  1395.         }
  1396.         xprintf("\n");
  1397.         return;
  1398.     }
  1399.     if (Isdigit(v[0][1])) {
  1400.         signum = atoi(short2str(v[0] + 1));
  1401.         if (signum < 0 || signum > NSIG)
  1402.         stderror(ERR_NAME | ERR_BADSIG);
  1403.     }
  1404.     else {
  1405.         for (signum = 1; signum <= NSIG; signum++)
  1406.         if (mesg[signum].iname &&
  1407.             eq(&v[0][1], str2short(mesg[signum].iname)))
  1408.             goto gotsig;
  1409.         setname(short2str(&v[0][1]));
  1410.         stderror(ERR_NAME | ERR_UNKSIG);
  1411.     }
  1412. gotsig:
  1413.     v++;
  1414.     }
  1415.     else
  1416.     signum = SIGTERM;
  1417.     pkill(v, signum);
  1418. }
  1419.  
  1420. static void
  1421. pkill(v, signum)
  1422.     Char  **v;
  1423.     int     signum;
  1424. {
  1425.     register struct process *pp, *np;
  1426.     int jobflags = 0, err1 = 0;
  1427.     pid_t     pid;
  1428. #ifdef BSDSIGS
  1429.     sigmask_t omask;
  1430. #endif /* BSDSIGS */
  1431.     Char   *cp;
  1432.  
  1433. #ifdef BSDSIGS
  1434.     omask = sigmask(SIGCHLD);
  1435.     if (setintr)
  1436.     omask |= sigmask(SIGINT);
  1437.     omask = sigblock(omask) & ~omask;
  1438. #else /* !BSDSIGS */
  1439.     if (setintr)
  1440.     (void) sighold(SIGINT);
  1441.     (void) sighold(SIGCHLD);
  1442. #endif /* !BSDSIGS */
  1443.     gflag = 0, tglob(v);
  1444.     if (gflag) {
  1445.     v = globall(v);
  1446.     if (v == 0)
  1447.         stderror(ERR_NAME | ERR_NOMATCH);
  1448.     }
  1449.     else {
  1450.     v = gargv = saveblk(v);
  1451.     trim(v);
  1452.     }
  1453.  
  1454.     while (v && (cp = *v)) {
  1455.     if (*cp == '%') {
  1456.         np = pp = pfind(cp);
  1457.         do
  1458.         jobflags |= np->p_flags;
  1459.         while ((np = np->p_friends) != pp);
  1460. #ifdef BSDJOBS
  1461.         switch (signum) {
  1462.  
  1463.         case SIGSTOP:
  1464.         case SIGTSTP:
  1465.         case SIGTTIN:
  1466.         case SIGTTOU:
  1467.         if ((jobflags & PRUNNING) == 0) {
  1468. # ifdef SUSPENDED
  1469.             xprintf("%s: Already suspended\n",
  1470.                 short2str(cp));
  1471. # else /* !SUSPENDED */
  1472.             xprintf("%s: Already stopped\n",
  1473.                 short2str(cp));
  1474. # endif /* !SUSPENDED */
  1475.             err1++;
  1476.             goto cont;
  1477.         }
  1478.         break;
  1479.         /*
  1480.          * suspend a process, kill -CONT %, then type jobs; the shell
  1481.          * says it is suspended, but it is running; thanks jaap..
  1482.          */
  1483.         case SIGCONT:
  1484.         pstart(pp, 0);
  1485.         goto cont;
  1486.         }
  1487. #endif /* BSDJOBS */
  1488.         if (killpg(pp->p_jobid, signum) < 0) {
  1489.         xprintf("%s: %s\n", short2str(cp), strerror(errno));
  1490.         err1++;
  1491.         }
  1492. #ifdef BSDJOBS
  1493.         if (signum == SIGTERM || signum == SIGHUP)
  1494.         (void) killpg(pp->p_jobid, SIGCONT);
  1495. #endif /* BSDJOBS */
  1496.     }
  1497.     else if (!(Isdigit(*cp) || *cp == '-'))
  1498.         stderror(ERR_NAME | ERR_JOBARGS);
  1499.     else {
  1500.         pid = atoi(short2str(cp));
  1501.         if (kill(pid, signum) < 0) {
  1502.         xprintf("%d: %s\n", pid, strerror(errno));
  1503.         err1++;
  1504.         goto cont;
  1505.         }
  1506. #ifdef BSDJOBS
  1507.         if (signum == SIGTERM || signum == SIGHUP)
  1508.         (void) kill(pid, SIGCONT);
  1509. #endif /* BSDJOBS */
  1510.     }
  1511. cont:
  1512.     v++;
  1513.     }
  1514.     if (gargv)
  1515.     blkfree(gargv), gargv = 0;
  1516. #ifdef BSDSIGS
  1517.     (void) sigsetmask(omask);
  1518. #else /* !BSDSIGS */
  1519.     (void) sigrelse(SIGCHLD);
  1520.     if (setintr)
  1521.     (void) sigrelse(SIGINT);
  1522. #endif /* !BSDSIGS */
  1523.     if (err1)
  1524.     stderror(ERR_SILENT);
  1525. }
  1526.  
  1527. /*
  1528.  * pstart - start the job in foreground/background
  1529.  */
  1530. void
  1531. pstart(pp, foregnd)
  1532.     register struct process *pp;
  1533.     int     foregnd;
  1534. {
  1535.     register struct process *np;
  1536. #ifdef BSDSIGS
  1537.     sigmask_t omask;
  1538. #endif /* BSDSIGS */
  1539.     long    jobflags = 0;
  1540.  
  1541. #ifdef BSDSIGS
  1542.     omask = sigblock(sigmask(SIGCHLD));
  1543. #else /* !BSDSIGS */
  1544.     (void) sighold(SIGCHLD);
  1545. #endif
  1546.     np = pp;
  1547.     do {
  1548.     jobflags |= np->p_flags;
  1549.     if (np->p_flags & (PRUNNING | PSTOPPED)) {
  1550.         np->p_flags |= PRUNNING;
  1551.         np->p_flags &= ~PSTOPPED;
  1552.         if (foregnd)
  1553.         np->p_flags |= PFOREGND;
  1554.         else
  1555.         np->p_flags &= ~PFOREGND;
  1556.     }
  1557.     } while ((np = np->p_friends) != pp);
  1558.     if (!foregnd)
  1559.     pclrcurr(pp);
  1560.     (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
  1561. #ifdef BSDJOBS
  1562.     if (foregnd)
  1563.     (void) tcsetpgrp(FSHTTY, pp->p_jobid);
  1564.     if (jobflags & PSTOPPED)
  1565.     (void) killpg(pp->p_jobid, SIGCONT);
  1566. #endif /* BSDJOBS */
  1567. #ifdef BSDSIGS
  1568.     (void) sigsetmask(omask);
  1569. #else /* !BSDSIGS */
  1570.     (void) sigrelse(SIGCHLD);
  1571. #endif /* !BSDSIGS */
  1572. }
  1573.  
  1574. void
  1575. panystop(neednl)
  1576.     bool    neednl;
  1577. {
  1578.     register struct process *pp;
  1579.  
  1580.     chkstop = 2;
  1581.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  1582.     if (pp->p_flags & PSTOPPED)
  1583.         stderror(ERR_STOPPED, neednl ? "\n" : "");
  1584. }
  1585.  
  1586. struct process *
  1587. pfind(cp)
  1588.     Char   *cp;
  1589. {
  1590.     register struct process *pp, *np;
  1591.  
  1592.     if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
  1593.     if (pcurrent == PNULL)
  1594.         stderror(ERR_NAME | ERR_JOBCUR);
  1595.     return (pcurrent);
  1596.     }
  1597.     if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
  1598.     if (pprevious == PNULL)
  1599.         stderror(ERR_NAME | ERR_JOBPREV);
  1600.     return (pprevious);
  1601.     }
  1602.     if (Isdigit(cp[1])) {
  1603.     int     idx = atoi(short2str(cp + 1));
  1604.  
  1605.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  1606.         if (pp->p_index == idx && pp->p_pid == pp->p_jobid)
  1607.         return (pp);
  1608.     stderror(ERR_NAME | ERR_NOSUCHJOB);
  1609.     }
  1610.     np = PNULL;
  1611.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  1612.     if (pp->p_pid == pp->p_jobid) {
  1613.         if (cp[1] == '?') {
  1614.         register Char *dp;
  1615.  
  1616.         for (dp = pp->p_command; *dp; dp++) {
  1617.             if (*dp != cp[2])
  1618.             continue;
  1619.             if (prefix(cp + 2, dp))
  1620.             goto match;
  1621.         }
  1622.         }
  1623.         else if (prefix(cp + 1, pp->p_command)) {
  1624.     match:
  1625.         if (np)
  1626.             stderror(ERR_NAME | ERR_AMBIG);
  1627.         np = pp;
  1628.         }
  1629.     }
  1630.     if (np)
  1631.     return (np);
  1632.     stderror(ERR_NAME | cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB);
  1633.     /* NOTREACHED */
  1634.     return (0);
  1635. }
  1636.  
  1637.  
  1638. /*
  1639.  * pgetcurr - find most recent job that is not pp, preferably stopped
  1640.  */
  1641. static struct process *
  1642. pgetcurr(pp)
  1643.     register struct process *pp;
  1644. {
  1645.     register struct process *np;
  1646.     register struct process *xp = PNULL;
  1647.  
  1648.     for (np = proclist.p_next; np; np = np->p_next)
  1649.     if (np != pcurrent && np != pp && np->p_pid &&
  1650.         np->p_pid == np->p_jobid) {
  1651.         if (np->p_flags & PSTOPPED)
  1652.         return (np);
  1653.         if (xp == PNULL)
  1654.         xp = np;
  1655.     }
  1656.     return (xp);
  1657. }
  1658.  
  1659. /*
  1660.  * donotify - flag the job so as to report termination asynchronously
  1661.  */
  1662. /*ARGSUSED*/
  1663. void
  1664. donotify(v, c)
  1665.     Char  **v;
  1666.     struct command *c;
  1667. {
  1668.     register struct process *pp;
  1669.  
  1670.     pp = pfind(*++v);
  1671.     pp->p_flags |= PNOTIFY;
  1672. }
  1673.  
  1674. /*
  1675.  * Do the fork and whatever should be done in the child side that
  1676.  * should not be done if we are not forking at all (like for simple builtin's)
  1677.  * Also do everything that needs any signals fiddled with in the parent side
  1678.  *
  1679.  * Wanttty tells whether process and/or tty pgrps are to be manipulated:
  1680.  *    -1:    leave tty alone; inherit pgrp from parent
  1681.  *     0:    already have tty; manipulate process pgrps only
  1682.  *     1:    want to claim tty; manipulate process and tty pgrps
  1683.  * It is usually just the value of tpgrp.
  1684.  */
  1685.  
  1686. int
  1687. pfork(t, wanttty)
  1688.     struct command *t;        /* command we are forking for */
  1689.     int     wanttty;
  1690. {
  1691.     register int pid;
  1692.     bool    ignint = 0;
  1693.     int     pgrp;
  1694. #ifdef BSDSIGS
  1695.     sigmask_t omask;
  1696. #endif /* BSDSIGS */
  1697. #if SIGSYNCH
  1698.     sigvec_t osv;
  1699.     static sigvec_t nsv = {synch_handler, ~0, 0};
  1700. #endif /* SIGSYNCH */
  1701.  
  1702.     /*
  1703.      * A child will be uninterruptible only under very special conditions.
  1704.      * Remember that the semantics of '&' is implemented by disconnecting the
  1705.      * process from the tty so signals do not need to ignored just for '&'.
  1706.      * Thus signals are set to default action for children unless: we have had
  1707.      * an "onintr -" (then specifically ignored) we are not playing with
  1708.      * signals (inherit action)
  1709.      */
  1710.     if (setintr)
  1711.     ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
  1712.         || (gointr && eq(gointr, STRminus));
  1713.     /*
  1714.      * Check for maximum nesting of 16 processes to avoid Forking loops
  1715.      */
  1716.     if (child == 16)
  1717.     stderror(ERR_NESTING, 16);
  1718.     /*
  1719.      * Hold SIGCHLD until we have the process installed in our table.
  1720.      */
  1721. #ifdef SIGSYNCH
  1722.     if (mysigvec(SIGSYNCH, &nsv, &osv))
  1723.     stderror(ERR_SYSTEM, "pfork: sigvec set", strerror(errno));
  1724. #endif /* SIGSYNCH */
  1725. #ifdef BSDSIGS
  1726.     omask = sigblock(sigmask(SIGCHLD));
  1727. #else /* !BSDSIGS */
  1728.     (void) sighold(SIGCHLD);
  1729. #endif /* !BSDSIGS */
  1730.     while ((pid = fork()) < 0)
  1731.     if (setintr == 0)
  1732.         (void) sleep(FORKSLEEP);
  1733.     else {
  1734. #ifdef BSDSIGS
  1735.         (void) sigsetmask(omask);
  1736. #else /* !BSDSIGS */
  1737.         (void) sigrelse(SIGINT);
  1738.         (void) sigrelse(SIGCHLD);
  1739. #endif /* !BSDSIGS */
  1740.         stderror(ERR_NOPROC);
  1741.     }
  1742.     if (pid == 0) {
  1743.     settimes();
  1744.     pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
  1745.     pflushall();
  1746.     pcurrjob = PNULL;
  1747. #if !defined(BSDTIMES) && !defined(_SEQUENT_) 
  1748.     timesdone = 0;
  1749. #endif /* !defined(BSDTIMES) && !defined(_SEQUENT_) */
  1750.     child++;
  1751.     if (setintr) {
  1752.         setintr = 0;    /* until I think otherwise */
  1753. #ifndef BSDSIGS
  1754.         (void) sigrelse(SIGCHLD);
  1755. #endif /* !BSDSIGS */
  1756.         /*
  1757.          * Children just get blown away on SIGINT, SIGQUIT unless "onintr
  1758.          * -" seen.
  1759.          */
  1760.         (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
  1761.         (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
  1762. #ifdef BSDJOBS
  1763.         if (wanttty >= 0) {
  1764.         /* make stoppable */
  1765. # ifdef __MINT__
  1766. /* see comments for sig_tmp_ign above */
  1767.         (void) signal(SIGTSTP, sig_tmp_ign);
  1768.         (void) signal(SIGTTIN, sig_tmp_ign);
  1769.         (void) signal(SIGTTOU, sig_tmp_ign);
  1770. # else
  1771.         (void) signal(SIGTSTP, SIG_DFL);
  1772.         (void) signal(SIGTTIN, SIG_DFL);
  1773.         (void) signal(SIGTTOU, SIG_DFL);
  1774. # endif
  1775.         }
  1776. #endif /* BSDJOBS */
  1777.         (void) signal(SIGTERM, parterm);
  1778.     }
  1779.     else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
  1780.         (void) signal(SIGINT, SIG_IGN);
  1781.         (void) signal(SIGQUIT, SIG_IGN);
  1782.     }
  1783. #ifdef OREO
  1784.     sigignore(SIGIO);    /* ignore SIGIO in child too */
  1785. #endif /* OREO */
  1786.  
  1787.     pgetty(wanttty, pgrp);
  1788.     /*
  1789.      * Nohup and nice apply only to NODE_COMMAND's but it would be nice
  1790.      * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
  1791.      * to know about nice/nohup/time
  1792.      */
  1793.     if (t->t_dflg & F_NOHUP)
  1794.         (void) signal(SIGHUP, SIG_IGN);
  1795.     if (t->t_dflg & F_NICE)
  1796. #ifdef BSDNICE
  1797.         (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
  1798. #else /* !BSDNICE */
  1799.         (void) nice(t->t_nice);
  1800. #endif /* !BSDNICE */
  1801. #ifdef F_VER
  1802.         if (t->t_dflg & F_VER) {
  1803.         Setenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
  1804.         dohash(NULL, NULL);
  1805.     }
  1806. #endif /* F_VER */
  1807. #ifdef SIGSYNCH
  1808.     /* rfw 8/89 now parent can continue */
  1809.     if (kill(getppid(), SIGSYNCH))
  1810.         stderror(ERR_SYSTEM, "pfork child: kill", strerror(errno));
  1811. #endif /* SIGSYNCH */
  1812.  
  1813.     }
  1814.     else {
  1815. #ifdef POSIXJOBS
  1816.     if (wanttty >= 0)
  1817.         (void) setpgid(pid, pcurrjob ? pcurrjob->p_jobid : pid);
  1818. #endif /* POSIXJOBS */
  1819.     palloc(pid, t);
  1820. #ifdef SIGSYNCH
  1821.     /*
  1822.      * rfw 8/89 Wait for child to own terminal.  Solves half of ugly
  1823.      * synchronization problem.  With this change, we know that the only
  1824.      * reason setpgrp to a previous process in a pipeline can fail is that
  1825.      * the previous process has already exited. Without this hack, he may
  1826.      * either have exited or not yet started to run.  Two uglies become
  1827.      * one.
  1828.      */
  1829.     sigpause(omask & ~SYNCHMASK);
  1830.     if (mysigvec(SIGSYNCH, &osv, NULL))
  1831.         stderror(ERR_SYSTEM, "pfork parent: sigvec restore",
  1832.              strerror(errno));
  1833. #endif /* SIGSYNCH */
  1834.  
  1835. #ifdef BSDSIGS
  1836.     (void) sigsetmask(omask);
  1837. #else /* !BSDSIGS */
  1838.     (void) sigrelse(SIGCHLD);
  1839. #endif /* !BSDSIGS */
  1840.     }
  1841.     return (pid);
  1842. }
  1843.  
  1844. static void
  1845. okpcntl()
  1846. {
  1847.     if (tpgrp == -1)
  1848.     stderror(ERR_JOBCONTROL);
  1849.     if (tpgrp == 0)
  1850.     stderror(ERR_JOBCTRLSUB);
  1851. }
  1852.  
  1853. /*
  1854.  * if we don't have vfork(), things can still go in the wrong order
  1855.  * resulting in the famous 'Stopped (tty output)'. But some systems
  1856.  * don't permit the setpgid() call, (these are more recent secure
  1857.  * systems such as ibm's aix), when they do. Then we'd rather print 
  1858.  * an error message than hang the shell!
  1859.  * I am open to suggestions how to fix that.
  1860.  */
  1861. void
  1862. pgetty(wanttty, pgrp)
  1863.     int     wanttty, pgrp;
  1864. {
  1865. #ifdef BSDJOBS
  1866. # if defined(BSDSIGS) && defined(POSIXJOBS)
  1867.     sigmask_t omask = 0;
  1868. # endif /* BSDSIGS && POSIXJOBS */
  1869.  
  1870. # ifdef JOBDEBUG
  1871.     xprintf("wanttty %d\n", wanttty);
  1872. # endif
  1873.  
  1874. # ifdef POSIXJOBS
  1875.     /*
  1876.      * christos: I am blocking the tty signals till I've set things
  1877.      * correctly....
  1878.      */
  1879.     if (wanttty > 0)
  1880. #  ifdef BSDSIGS
  1881.     omask = sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU));
  1882. #  else /* !BSDSIGS */
  1883.     {
  1884.     (void) sighold(SIGTSTP);
  1885.     (void) sighold(SIGTTIN);
  1886.     (void) sighold(SIGTTOU);
  1887.     }
  1888. #  endif /* !BSDSIGS */
  1889.  
  1890.     /*
  1891.      * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
  1892.      * Don't check for tpgrp >= 0 so even non-interactive shells give
  1893.      * background jobs process groups Same for the comparison in the other part
  1894.      * of the #ifdef
  1895.      */
  1896.     if (wanttty >= 0)
  1897.     if (setpgid(0, pgrp) == -1) {
  1898. #  if !defined(ISC) && !defined(SCO)
  1899.         /* XXX: Wrong but why? */
  1900.         xprintf("tcsh: setpgid error (%s).\n", strerror(errno));
  1901.         xexit(0);
  1902. #  endif /* !ISC && !SCO */
  1903.     }
  1904. # endif /* POSIXJOBS */
  1905.  
  1906.     if (wanttty > 0)
  1907.     (void) tcsetpgrp(FSHTTY, pgrp);
  1908.  
  1909. # ifndef POSIXJOBS
  1910.     if (wanttty >= 0)
  1911.     if (setpgid(0, pgrp) == -1) {
  1912. #  if !defined(ISC) && !defined(SCO)
  1913.         /* XXX: Wrong but why? */
  1914.         xprintf("tcsh: setpgid error (%s).\n", strerror(errno));
  1915.         xexit(0);
  1916. #  endif /* !ISC && !SCO */
  1917.     }
  1918. # else /* POSIXJOBS */
  1919.     if (wanttty > 0)
  1920. #  ifdef BSDSIGS
  1921.     (void) sigsetmask(omask);
  1922. #  else /* BSDSIGS */
  1923.     {
  1924.     (void) sigrelse(SIGTSTP);
  1925.     (void) sigrelse(SIGTTIN);
  1926.     (void) sigrelse(SIGTTOU);
  1927.     }
  1928. #  endif /* !BSDSIGS */
  1929. # endif /* POSIXJOBS */
  1930.  
  1931.     if (tpgrp > 0)
  1932.     tpgrp = 0;        /* gave tty away */
  1933. #endif /* BSDJOBS */
  1934. }
  1935.